from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QLabel
from qgis._core import QgsCoordinateReferenceSystem, QgsLayerTreeModel, QgsProject, QgsMapSettings, \
    QgsPointXY
from qgis._gui import QgsMapCanvas, QgsMapToolPan, QgsMapToolZoom, QgsLayerTreeView, QgsLayerTreeMapCanvasBridge

from gui.preview.functions import open_raster_file, open_shp_file, slot_refresh_canvas, slot_set_gis_tool
from utils.raster import convert_to_wgs84


def load_preview(self):
    """
    装载预览界面
    :param self:
    :return:
    """
    # 初始化界面变量
    declaring_variable(self)
    # 初始化界面布局
    init_preview(self)
    # 初始化 QGIS
    init_qgis_map(self)
    # 绑定方法
    bind_func(self)


def declaring_variable(self):
    self.preview_canvas = None  # 图层显示器
    self.preview_tool_pan = None
    self.preview_tool_zoom_in = None
    self.preview_tool_zoom_out = None


def init_preview(self):
    # 设置splitter缩放因子
    self.ui.splitter.setStretchFactor(0, 3)
    self.ui.splitter.setStretchFactor(1, 5)


def set_status_crs(label: QLabel, canvas: QgsMapCanvas):
    canvas.mapSettings().destinationCrs().description()
    map_setting: QgsMapSettings = canvas.mapSettings()
    label.setText(f"坐标系: {map_setting.destinationCrs().description()}-{map_setting.destinationCrs().authid()}")


def init_qgis_map(self):
    # 注意,这个函数很重要
    # 初始化画布
    self.preview_canvas = QgsMapCanvas()
    self.preview_canvas.setDestinationCrs(QgsCoordinateReferenceSystem("EPSG:4326"))
    self.preview_canvas.setCanvasColor(Qt.white)
    self.preview_canvas.enableAntiAliasing(True)
    self.preview_canvas.setFocus()
    self.preview_canvas.setParallelRenderingEnabled(True)
    set_status_crs(self.ui.label_crs, self.preview_canvas)
    # 添加到布局中
    # 有一个控件的layoutName名叫preview_qgis_map,你需要手动设置
    # 这里就是把main.preview_canvas加入到这个preview_qgis_map这个东西里
    self.ui.preview_qgis_map.addWidget(self.preview_canvas)

    # 初始化画布的时候，设置状态栏的坐标参考系统
    set_status_crs(self.ui.label_crs, self.preview_canvas)
    # 初始化工具
    self.preview_tool_pan = QgsMapToolPan(self.preview_canvas)
    self.preview_tool_zoom_in = QgsMapToolZoom(self.preview_canvas, False)
    self.preview_tool_zoom_out = QgsMapToolZoom(self.preview_canvas, True)
    # 默认使用移动工具
    self.preview_canvas.setMapTool(self.preview_tool_pan)

    # 初始化图层管理器
    # 创建图层树视图，然后添加到界面中
    self.layerTreeView = QgsLayerTreeView(self)
    self.ui.layout_prev_layers.addWidget(self.layerTreeView)
    # 树节点
    self.model = QgsLayerTreeModel(QgsProject.instance().layerTreeRoot(), self)
    self.model.setFlag(QgsLayerTreeModel.AllowNodeRename)  # 允许图层节点重命名
    self.model.setFlag(QgsLayerTreeModel.AllowNodeReorder)  # 允许图层拖拽排序
    self.model.setFlag(QgsLayerTreeModel.AllowNodeChangeVisibility)  # 允许改变图层节点可视性
    self.model.setFlag(QgsLayerTreeModel.ShowLegendAsTree)  # 展示图例
    self.model.setAutoCollapseLegendNodes(10)  # 当节点数大于等于10时自动折叠
    self.layerTreeView.setModel(self.model)
    # 4 建立图层树与地图画布的桥接
    self.layerTreeBridge = QgsLayerTreeMapCanvasBridge(QgsProject.instance().layerTreeRoot(), self.preview_canvas, self)


def set_status_xy(label_origin, label_latlon, canvas: QgsMapCanvas, point: QgsPointXY):
    label_origin.setText(f'{point.x():.0f}, {point.y():.0f}')
    convert_point = convert_to_wgs84(QgsCoordinateReferenceSystem(canvas.mapSettings().destinationCrs().authid()),
                                     point)
    label_latlon.setText(f'{convert_point.y():.5f}°, {convert_point.x():.5f}°')
    label_latlon.setCursorPosition(0)


def bind_func(self):
    _ui = self.ui
    # 添加栅格数据按钮绑定方法
    _ui.button_add_raster.clicked.connect(lambda self: open_raster_file(self))
    # 添加矢量数据按钮绑定方法
    _ui.button_add_shp.clicked.connect(lambda self: open_shp_file(self))
    # 绑定工具方法
    _ui.button_move.clicked.connect(lambda self: slot_set_gis_tool(self.preview_canvas, self.preview_tool_pan))
    _ui.button_zoom_in.clicked.connect(lambda self: slot_set_gis_tool(self.preview_canvas, self.preview_tool_zoom_in))
    _ui.button_zoom_out.clicked.connect(lambda self: slot_set_gis_tool(self.preview_canvas, self.preview_tool_zoom_out))
    _ui.button_refresh.clicked.connect(lambda self: slot_refresh_canvas(self.preview_canvas))
    # qgis map 鼠标移动时坐标更改事件
    self.preview_canvas.xyCoordinates.connect(
        lambda point: set_status_xy(_ui.edit_coords_default_value, _ui.edit_coords_value, self.preview_canvas, point))
